PAGE 118,121
TITLE TEST2 ---- 11/15/85  POST TESTS AND INITIALIZATION ROUTINES
.286C
.287
.XLIST
INCLUDE DSEG.INC
INCLUDE POSTEQU.INC
INCLUDE SYSDATA.INC
.LIST
CODE	SEGMENT BYTE PUBLIC
	PUBLIC	C21
	PUBLIC	POST2
	PUBLIC	SHUT2
	PUBLIC	SHUT3
	PUBLIC	SHUT4
	PUBLIC	SHUT6
	PUBLIC	SHUT7

	EXTRN	BLINK_INT:NEAR
	EXTRN	C8042:NEAR
	EXTRN	CMOS_READ:NEAR
	EXTRN	CMOS_WRITE:NEAR
	EXTRN	CONFIG_BAD:NEAR
	EXTRN	D1:NEAR
	EXTRN	D2:NEAR
	EXTRN	DDS:NEAR
	EXTRN	DISK_SETUP:NEAR
	EXTRN	DSKETTE_SETUP:NEAR
	EXTRN	ERR_BEEP:NEAR
	EXTRN	E_MSG:NEAR
	EXTRN	F3D:NEAR
	EXTRN	F3D1:NEAR
	EXTRN	GATE_A20:NEAR
	EXTRN	HD_INT:NEAR
	EXTRN	KBD_RESET:NEAR
	EXTRN	NMI_INT:NEAR
	EXTRN	OBF_42:NEAR
	EXTRN	POST3:NEAR
	EXTRN	PRINT_SCREEN:NEAR
	EXTRN	PROC_SHUTDOWN:NEAR
	EXTRN	PROT_PRT_HEX:NEAR
	EXTRN	PRT_HEX:NEAR
	EXTRN	P_MSG:NEAR
	EXTRN	ROM_CHECK:NEAR
	EXTRN	ROM_CHECKSUM:NEAR
	EXTRN	SEEK:NEAR
	EXTRN	SET_TOD:NEAR
	EXTRN	SLAVE_VECTOR_TABLE:NEAR
	EXTRN	SND_DATA:NEAR
	EXTRN	START_1:NEAR
	EXTRN	STGTST_CNT:NEAR
	EXTRN	SYSINIT1:NEAR
	EXTRN	VECTOR_TABLE:NEAR
	EXTRN	WAITF:NEAR
	EXTRN	XPC_BYTE:NEAR

	EXTRN	E101:NEAR		; 101 ERROR CODE - INTERRUPT FAILURE
	EXTRN	E102:NEAR		; 102 ERROR CODE - TIMER FAILURE
	EXTRN	E103:NEAR		; 103 ERROR CODE - TIMER INTERRUPT
	EXTRN	E104:NEAR		; 104 ERROR CODE - PROTECTED MODE ERROR
	EXTRN	E105:NEAR		; 105 ERROR CODE - 8042 COMMAND FAILURE
	EXTRN	E106:NEAR		; 106 ERROR CODE - CONVERTING LOGIC
	EXTRN	E107:NEAR		; 107 ERROR CODE - NMI ERROR
	EXTRN	E108:NEAR		; 108 ERROR CODE - TIMER BUS ERROR
	EXTRN	E109:NEAR		; 109 ERROR CODE - MEMORY SELECT ERROR
	EXTRN	E161:NEAR		; 161 ERROR CODE - BAD BATTERY
	EXTRN	E162:NEAR		; 162 ERROR CODE - CMOS CHECKSUM/CONFIG
	EXTRN	E163:NEAR		; 163 ERROR CODE - BAD REAL TIME CLOCK
	EXTRN	E164:NEAR		; 164 ERROR CODE - MEMORY SIZE WRONG
	EXTRN	E201:NEAR		; 201 ERROR CODE - MEMORY DATA ERROR
	EXTRN	E202:NEAR		; 202 ERROR CODE - MEMORY ADDRESS ERROR
	EXTRN	E203:NEAR		; 203 ERROR CODE - SEGMENT ADDRESS ERROR
	EXTRN	E301:NEAR		; 301 ERROR CODE - KEYBOARD ERROR
	EXTRN	E302:NEAR		; 302 ERROR CODE - LOCK IS ON
	EXTRN	E303:NEAR		; 303 ERROR CODE - KEYBOARD/PLANAR ERROR
	EXTRN	E304:NEAR		; 304 ERROR CODE - KEYBOARD/PLANAR ERROR
	EXTRN	E401:NEAR		; 401 ERROR CODE - MONOCHROME ADAPTER
	EXTRN	E501:NEAR		; 501 ERROR CODE - COLOR ADAPTER
	EXTRN	E601:NEAR		; 601 ERROR CODE - DISKETTE ADAPTER

;--------------------------------------------------------
; TEST.17						:
;	8259 INTERRUPT CONTROLLER TEST			:
; DESCRIPTION						:
;	READ/WRITE THE INTERRUPT MASK REGISTER (IMR)	:
;	WITH ALL ONES AND ZEROES, ENABLE SYSTEM 	:
;	INTERRUPTS,  MASK DEVICE INTERRUPTS OFF. CHECK	:
;	FOR HOT INTERRUPTS (UNEXPECTED).		:
;--------------------------------------------------------

	ASSUME	CS:CODE,DS:DATA

POST2	PROC	NEAR

C21:	MOV	AL,10			; LINE FEED ON DISPLAY
	CALL	PRT_HEX
	CALL	DDS			; SET DATA SEGMENT

;-----	CLEAR ERROR FLAG REGISTER (BP) <=> 0 FLAGS ERROR

	SUB	BP,BP			; CLEAR (BP) REGISTER AS ERROR FLAG REG

;------ TEST THE INTERRUPT MASK REGISTER REGISTERS

C21A:	CLI				; TURN OFF INTERRUPTS
	MOV	AL,0			; SET INTERRUPT MASK REGISTER TO ZERO
	OUT	INTA01,AL
	OUT	INTB01,AL		; SEND TO 2ND INTERRUPT CONTROLLER ALSO
	JMP	$+2
	IN	AL,INTA01		; READ INTERRUPT MASK REGISTER
	MOV	AH,AL			; SAVE RESULTS
	IN	AL,INTB01		; READ 2ND INTERRUPT MASK REGISTER

	OR	AH,AL			; BOTH IMR = 0?
	JNZ	D6			; GO TO ERR ROUTINE IF NOT 0

	MOV	AL,25H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  25 <><>

	MOV	AL,0FFH 		; DISABLE DEVICE INTERRUPTS
	OUT	INTA01,AL		; WRITE TO INTERRUPT MASK REGISTER
	OUT	INTB01,AL		; WRITE TO 2ND INTERRUPT MASK REGISTER
	JMP	$+2			; I/O DELAY
	IN	AL,INTA01		; READ INTERRUPT MASK REGISTER
	MOV	AH,AL			; SAVE RESULTS
	IN	AL,INTB01		; READ 2ND INTERRUPT MASK REGISTER

	ADD	AX,1			; ALL IMR BITS ON?
	JNZ	D6			; NO - GO TO ERR ROUTINE

;-----	CHECK FOR HOT INTERRUPTS

;-----	INTERRUPTS ARE MASKED OFF, CHECK THAT NO INTERRUPTS OCCUR.

	MOV	@INTR_FLAG,AL		; CLEAR INTERRUPT FLAG

	MOV	AL,26H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  26 <><>

	STI				; ENABLE EXTERNAL INTERRUPTS
	MOV	CX,6628 		; WAIT 100 MILLISECONDS FOR ANY
	CALL	WAITF			;  INTERRUPTS THAT OCCUR
	CMP	@INTR_FLAG,00H		; DID ANY INTERRUPTS OCCUR?
	JZ	D7			; NO - GO TO NEXT TEST

D6:	MOV	@MFG_ERR_FLAG,05H	;	<><><><><><><><><><><><>
					;	<><> CHECKPOINT   5 <><>
	MOV	SI,OFFSET E101		; DISPLAY 101 ERROR
D6A:	CALL	E_MSG
	CLI
	HLT				; HALT THE SYSTEM

;-----	CHECK THE CONVERTING LOGIC

D7:	MOV	AL,27H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  27 <><>

	MOV	AX,0AA55H
	OUT	MFG_PORT+2,AX		; WRITE A WORD
	IN	AL,MFG_PORT+2		;  GET THE FIRST BYTE
	XCHG	AL,AH			;  SAVE IT
	IN	AL,MFG_PORT+3		;  GET THE SECOND BYTE
	CMP	AX,55AAH		; IS IT OK?
	JZ	D7_A			; GO IF YES

	MOV	SI,OFFSET E106		; DISPLAY 106 ERROR
	JMP	D6A

;-----	CHECK FOR HOT NMI INTERRUPTS WITHOUT I/O-MEMORY PARITY ENABLED

D7_A:
	MOV	AL,CMOS_REG_D		; TURN ON NMI
	OUT	CMOS_PORT,AL		; ADDRESS DEFAULT READ ONLY REGISTER
	MOV	CX,7			; DELAY COUNT FOR 100 MICROSECONDS
	CALL	WAITF			; WAIT FOR HOT NMI TO PROCESS
	MOV	AL,CMOS_REG_D+NMI	; TURN NMI ENABLE BACK OFF
	OUT	CMOS_PORT,AL
	CMP	@INTR_FLAG,00H		; DID ANY INTERRUPTS OCCUR?
	JZ	D7_C			; CONTINUE IF NOT

	MOV	AL,28H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  28 <><>

	MOV	SI,OFFSET E107		; DISPLAY 107 ERROR
	JMP	D6A

;-----	TEST THE DATA BUS TO TIMER 2

D7_C:	MOV	AL,29H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  29 <><>
	IN	AL,PORT_B		; GET CURRENT SETTING OF PORT
	MOV	AH,AL			; SAVE THAT SETTING
	AND	AL,0FCH 		; INSURE SPEAKER OFF
	OUT	PORT_B,AL

	MOV	AL,10110000B		; SELECT TIM 2,LSB,MSB,BINARY,MODE 0
	OUT	TIMER+3,AL		; WRITE THE TIMER MODE REGISTER
	JMP	$+2			; I/O DELAY
	MOV	AX,0AA55H		; WRITE AN AA55
	OUT	TIMER+2,AL		; WRITE TIMER 2 COUNT - LSB
	JMP	$+2			; I/O DELAY
	MOV	AL,AH
	OUT	TIMER+2,AL		; WRITE TIMER 2 COUNT - MSB
	JMP	$+2			; I/O DELAY
	IN	AL,TIMER+2		; GET THE LSB
	XCHG	AH,AL			; SAVE IT
	JMP	$+2			; I/O DELAY
	IN	AL,TIMER+2		; GET THE MSB
	CMP	AX,055AAH		; BUS OK?
	JZ	D7_D			; GO IF OK

	MOV	SI,OFFSET E108		; DISPLAY 108 ERROR
	JMP	D6A

;--------------------------------------------------------
; TEST.18						:
;	8254 TIMER CHECKOUT				:
; DESCRIPTION						:
;	VERIFY THAT THE SYSTEM TIMER (0) DOESN'T COUNT  :
;	TOO FAST OR TOO SLOW.				:
;--------------------------------------------------------

D7_D:	MOV	AL,2AH			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  2A <><>
	CLI
	MOV	AL,0FEH 		; MASK ALL INTERRUPTS EXCEPT LEVEL 0
	OUT	INTA01,AL		; WRITE THE 8259 IMR
	MOV	AL,00010000B		; SELECT TIM 0, LSB, MODE 0, BINARY
	OUT	TIMER+3,AL		; WRITE TIMER CONTROL MODE REGISTER
	MOV	CX,2CH			; SET PROGRAM LOOP COUNT

	JMP	$+2			; I/O DELAY

	MOV	AL,CL			; SET TIMER 0 COUNT REGISTER
	OUT	TIMER+0,AL		; WRITE TIMER 0 COUNT REGISTER
	STI
D8:	TEST	@INTR_FLAG,01H
					; DID TIMER 0 INTERRUPT OCCUR?
	JNZ	D9			; CHECK TIMER OPERATION FOR SLOW TIME
	LOOP	D8			; WAIT FOR INTERRUPT FOR SPECIFIED TIME

	MOV	@MFG_ERR_FLAG,02H	;	<><><><><><><><><><><><><><><>
					;	<><> TIMER CHECKPOINT (2) <><>

D8_A:	MOV	SI,OFFSET E102		; DISPLAY 102 ERROR
	JMP	D6A			; TIMER 0 INTERRUPT DID NOT OCCUR= ERROR


D9:	MOV	AL,2BH			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  2B <><>

	CLI
	MOV	CL,12			; SET PROGRAM LOOP COUNT
	MOV	AL,0FFH 		; WRITE TIMER 0 COUNT REGISTER
	OUT	TIMER+0,AL
	MOV	@INTR_FLAG,0		; RESET INTERRUPT RECEIVED FLAG
	MOV	AL,0FEH 		; RE-ENABLE TIMER 0 INTERRUPTS
	OUT	INTA01,AL
	STI
D10:	TEST	@INTR_FLAG,01H		; DID TIMER 0 INTERRUPT OCCUR?
	JNZ	D8_A			; YES - TIMER COUNTING TOO FAST, ERROR
	LOOP	D10			; WAIT FOR INTERRUPT FOR SPECIFIED TIME

;-----	WAIT FOR INTERRUPT

	SUB	CX,CX

	MOV	AL,2CH			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  2C <><>
D110:
	TEST	@INTR_FLAG,01H		; DID TIMER 0 INTERRUPT OCCUR?
	JNZ	D12			; GO IF YES
	LOOP	D110			; TRY AGAIN

	MOV	SI,OFFSET E103		; DISPLAY 103 ERROR
	JMP	D6A			; ERROR IF NOT

;-----	SETUP TIMER 0 TO MODE 3

D12:	CLI
	MOV	AL,0FFH 		; DISABLE ALL DEVICE INTERRUPTS
	OUT	INTA01,AL
	MOV	AL,36H			; SELECT TIMER 0,LSB,MSB,MODE 3
	OUT	TIMER+3,AL		; WRITE TIMER MODE REGISTER
	JMP	$+2			; I/O DELAY
	MOV	AL,0
	OUT	TIMER+0,AL		; WRITE LSB TO TIMER 0 REGISTER
	JMP	$+2			; I/O DELAY
	OUT	TIMER+0,AL		; WRITE MSB TO TIMER 0 REGISTER

;-----	CHECK 8042 FOR LAST COMMAND ACCEPTED

	SUB	CX,CX			; SET WAIT TIME
	MOV	AL,2DH			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  2D <><>
D13:	IN	AL,STATUS_PORT		; GET THE 8042 STATUS
	TEST	AL,INPT_BUF_FULL	; HAS THE LAST COMMAND BEEN ACCEPTED?
	JZ	E19			; GO IF YES
	LOOP	D13			; TRY AGAIN

;-----	ERROR EXIT (MESSAGE 105)

	MOV	SI,OFFSET E105		; PRINT 105 ERROR
	JMP	D6A			; GO ERROR HALT

;-------------------------------------------------------------------------
; TEST.19								 :
;	ADDITIONAL READ/WRITE STORAGE TEST				 :
;	++++ MUST RUN IN PROTECTED MODE ++++				 :
; DESCRIPTION								 :
;	WRITE/READ DATA PATTERNS TO ANY READ/WRITE STORAGE AFTER THE	 :
;	FIRST 64K.  STORAGE ADDRESSABILITY IS CHECKED.			 :
;-------------------------------------------------------------------------

	ASSUME	DS:DATA
E19:
	CALL	DDS			; SET DATA SEGMENT
	MOV	AL,2FH			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  2F <><>

	CMP	@RESET_FLAG,1234H	; WARM START?
	JNE	E19A			; GO IF NOT
	JMP	SHUT2			; GO TO NEXT TEST IF WARM START

;-----	SET SHUTDOWN RETURN 2

E19A:	MOV	AL,30H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  30 <><>

	MOV	AX,2*H+CMOS_SHUT_DOWN+NMI	; ADDRESS FOR SHUTDOWN BYTE
	CALL	CMOS_WRITE		; SECOND ENTRY IN SHUTDOWN TABLE

;-----	ENABLE PROTECTED MODE

	MOV	SP,POST_SS		; SET STACK FOR SYSINIT1
	MOV	SS,SP
	MOV	SP,POST_SP

	CALL	SYSINIT1		; GO ENABLE PROTECTED MODE

	MOV	AL,31H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  31 <><>

;-----	SET TEMPORARY STACK

	PUSH	BYTE PTR GDT_PTR
	POP	ES
	MOV	ES:SS_TEMP.BASE_LO_WORD,0
	MOV	BYTE PTR ES:(SS_TEMP.BASE_HI_BYTE),0
	MOV	SI,SS_TEMP
	MOV	SS,SI
	MOV	SP,MAX_SEG_LEN-2

;-----	DATA SEGMENT TO SYSTEM DATA AREA

	PUSH	BYTE PTR RSDA_PTR	; POINT TO DATA AREA
	POP	DS

	MOV	AL,PARITY_CHECK 	; SET CHECK PARITY
	OUT	DMA_PAGE+6,AL		; SAVE WHICH CHECK TO USE

;-----	PRINT 64 K BYTES OK

	MOV	AX,64			; STARTING AMOUNT OF MEMORY OK
	CALL	PRT_OK			; POST 64K OK MESSAGE

;-----	GET THE MEMORY SIZE DETERMINED (PREPARE BX AND DX FOR BAD CMOS)

	MOV	AX,(CMOS_U_M_S_LO+NMI)*H+CMOS_U_M_S_HI+NMI
	CALL	CMOS_READ		; HIGH BYTE
	XCHG	AH,AL			; SAVE HIGH BYTE
	CALL	CMOS_READ		; LOW BYTE
	MOV	BX,@MEMORY_SIZE 	; LOAD THE BASE MEMORY SIZE
	MOV	DX,BX			; SAVE BASE MEMORY SIZE
	ADD	BX,AX			; SET TOTAL MEMORY SIZE

;-----	IS CMOS GOOD?

	MOV	AL,CMOS_DIAG+NMI	; DETERMINE THE CONDITION OF CMOS
	CALL	CMOS_READ		; GET THE CMOS STATUS

	TEST	AL,BAD_BAT+BAD_CKSUM	; CMOS OK?
	JZ	E20B0			; GO IF YES
	JMP	SHORT E20C		; DEFAULT IF NOT

;-----	GET THE BASE 0->640K MEMORY SIZE FROM CONFIGURATION IN CMOS

E20B0:
	MOV	AX,(CMOS_B_M_S_LO+NMI)*H+CMOS_B_M_S_HI+NMI
	CALL	CMOS_READ		; HIGH BYTE
	AND	AL,03FH 		; MASK OFF THE MANUFACTURING TEST BITS
	XCHG	AH,AL			; SAVE HIGH BYTE
	CALL	CMOS_READ		; LOW BYTE OF BASE MEMORY SIZE
	CMP	DX,AX			; IS MEMORY SIZE GREATER THAN CONFIG?
	JZ	E20B1			; GO IF EQUAL

;-----	SET MEMORY SIZE DETERMINE NOT EQUAL TO CONFIGURATION

	PUSH	AX			; SAVE AX
	MOV	AX,X*(CMOS_DIAG+NMI)	; ADDRESS THE STATUS BYTE
	CALL	CMOS_READ		; GET THE STATUS
	OR	AL,W_MEM_SIZE		; SET CMOS FLAG
	XCHG	AL,AH			; SAVE AL AND GET ADDRESS
	CALL	CMOS_WRITE		; WRITE UPDATED STATUS
	POP	AX			; RESTORE AX
	CMP	DX,AX			; IS MEMORY SIZE GREATER THAN CONFIG ?
	JA	E20C			; DEFAULT TO MEMORY SIZE DETERMINED ?
E20B1:
	MOV	BX,AX			; SET BASE MEMORY SIZE IN TOTAL REGISTER
	MOV	DX,AX			; SAVE IN BASE SIZE REGISTER

;-----	CHECK MEMORY SIZE ABOVE 640K FROM CONFIGURATION

	MOV	AX,(CMOS_E_M_S_LO+NMI)*H+(CMOS_E_M_S_HI+NMI)
	CALL	CMOS_READ		; HIGH BYTE
	XCHG	AH,AL			; SAVE HIGH BYTE
	CALL	CMOS_READ		; LOW BYTE
	MOV	CX,AX			; SAVE THE ABOVE 640K MEMORY SIZE
;-----	ABOVE 640K SIZE FROM MEMORY SIZE DETERMINE
;-----	CX=CONFIG  AX=MEMORY SIZE DETERMINE
	MOV	AX,(CMOS_U_M_S_LO+NMI)*H+(CMOS_U_M_S_HI+NMI)
	CALL	CMOS_READ		; HIGH BYTE
	XCHG	AH,AL			; SAVE HIGH BYTE
	CALL	CMOS_READ		; LOW BYTE
;------ WHICH IS GREATER - AX = MEMORY SIZE DETERMINE
;------ CX = CONFIGURATION (ABOVE 640) BX = SIZE (BELOW 640)

	CMP	CX,AX			; IS CONFIGURATION EQUAL TO DETERMINED?
	JZ	SET_MEM1		; GO IF EQUAL

;-----	SET MEMORY SIZE DETERMINE NOT EQUAL TO CONFIGURATION

	PUSH	AX			; SAVE AX
	MOV	AX,X*(CMOS_DIAG+NMI)	; ADDRESS THE STATUS BYTE
	CALL	CMOS_READ		; GET THE STATUS
	OR	AL,W_MEM_SIZE		; SET CMOS FLAG
	XCHG	AL,AH			; SAVE AL
	CALL	CMOS_WRITE		; UPDATE STATUS BYTE
	POP	AX			; RESTORE AX

SET_MEM1:
	CMP	CX,AX			; IS CONFIG GREATER THAN DETERMINED?
	JA	SET_MEM 		; GO IF YES
	MOV	CX,AX			; USE MEMORY SIZE DETERMINE IF NOT
SET_MEM:
	ADD	BX,CX			; SET TOTAL MEMORY SIZE
E20C:
	CMP	DX,513			; CHECK IF BASE MEMORY LESS 512K
	JB	NO_640			; GO IF YES

	MOV	AX,X*(CMOS_INFO128+NMI) ; SET 640K BASE MEMORY BIT
	CALL	CMOS_READ		; GET THE CURRENT STATUS
	OR	AL,M640K		; TURN ON 640K BIT IF NOT ALREADY ON
	XCHG	AL,AH			; SAVE THE CURRENT DIAGNOSTIC STATUS
	CALL	CMOS_WRITE		; RESTORE THE STATUS
NO_640:
	MOV	WORD PTR @KB_FLAG,BX	; SAVE TOTAL SIZE FOR LATER TESTING
	SHR	BX,6			; DIVIDE BY 64
	DEC	BX			; 1ST 64K ALREADY DONE
	SHR	DX,6			; DIVIDE BY 64 FOR BASE

;-----	SAVE COUNTS IN STACK FOR BOTH MEMORY AND ADDRESSING TESTS

	PUSH	DX			; SAVE BASE MEMORY SIZE COUNT
	PUSH	BYTE PTR 64		; SAVE STARTING AMOUNT OF MEMORY OK
	PUSH	BX			; SAVE COUNT OF 64K BLOCKS TO BE TESTED

	PUSH	DX			; SAVE BASE MEMORY SIZE COUNT
	PUSH	BYTE PTR 64		; SAVE STARTING AMOUNT OF MEMORY OK
	PUSH	BX			; SAVE COUNT OF 64K BLOCKS TO BE TESTED

;-----	MODIFY DESCRIPTOR TABLES

	PUSH	BYTE PTR GDT_PTR	; MODIFY THE DESCRIPTOR TABLE
	POP	ES

;-----	SET TEMPORARY ES DESCRIPTOR 64K SEGMENT LIMIT STARTING AT 000000

	MOV	ES:ES_TEMP.SEG_LIMIT,MAX_SEG_LEN
	MOV	ES:ES_TEMP.BASE_LO_WORD,0
	MOV	BYTE PTR ES:(ES_TEMP.BASE_HI_BYTE),0		; FIRST 65K
	MOV	BYTE PTR ES:(ES_TEMP.DATA_ACC_RIGHTS),CPL0_DATA_ACCESS

;-----	SET TEMPORARY DS DESCRIPTOR 64K SEGMENT LIMIT AT FIRST 65K BLOCK

	MOV	ES:DS_TEMP.SEG_LIMIT,MAX_SEG_LEN
	MOV	ES:DS_TEMP.BASE_LO_WORD,0
	MOV	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),0
	MOV	BYTE PTR ES:(DS_TEMP.DATA_ACC_RIGHTS),CPL0_DATA_ACCESS

;-----	TEMPORARY SEGMENT SAVE IN DMA PAGE REGISTER FOR SECOND 65K BLOCK

	SUB	AL,AL			; INITIALIZE VALUES TO 010000
	OUT	DMA_PAGE+4,AL		; HIGH BYTE OF LOW WORD OF SEGMENT
	OUT	DMA_PAGE+5,AL		; LOW BYTE OF LOW WORD OF SEGMENT
	INC	AL			; SET HIGH BYTE OF SEGMENT WORD
	OUT	DMA_PAGE+3,AL		; HIGH BYTE OF SEGMENT

;-----	MEMORY TEST LOOP - POINT TO NEXT BLOCK OF 32K WORDS (64K)

E21:					;	MEMORY TEST LOOP
	PUSH	BYTE PTR GDT_PTR	; POINT TO START OF DESCRIPTOR TABLE
	POP	DS
	INC	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE)	; POINT TO NEXT BLOCK
	INC	BYTE PTR DS:(ES_TEMP.BASE_HI_BYTE)

;-----	CHECK FOR END OF 256K PLANAR MEMORY

	CMP	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),04H
	JB	E21_0			; GO IF STILL FIRST 256K OF BASE MEMORY

	MOV	AL,PARITY_CHECK+IO_CHECK; CHECK FOR ANY TYPE OF PARITY ERROR
	OUT	DMA_PAGE+6,AL		; AFTER FIRST 256K

;-----	CHECK END OF FIRST 640K OR ABOVE (END OF MAXIMUM BASE MEMORY)
E21_0:
	CMP	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),0AH
	JA	NEXT			; CONTINUE IF ABOVE 1 MEG

;-----	CHECK FOR END OF BASE MEMORY TO BE TESTED

	POP	CX			; GET COUNT
	POP	BX			; GET COUNT TESTED
	POP	AX			; RECOVER COUNT OF BASE MEMORY BLOCKS
	PUSH	AX			; SAVE BASE COUNT
	PUSH	BX			; SAVE TESTED COUNT
	PUSH	CX			; SAVE TOTAL COUNT
	CMP	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),AL		; MAX BASE COUNT
	JB	NEXT			; CONTINUE IF NOT DONE WITH BASE MEMORY

;-----	DO ADDITIONAL STORAGE ABOVE 1 MEG

	MOV	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),10H
	MOV	BYTE PTR DS:(ES_TEMP.BASE_HI_BYTE),10H

;-----	SAVE BASE_HI_BYTE IN DMA PAGE REGISTERS 3

NEXT:	MOV	AL,BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE)
	OUT	DMA_PAGE+3,AL		; SAVE THE HIGH BYTE OF SEGMENT
					;  FOR POSSIBLE ERROR

;-----	CHECK FOR TOP OF MEMORY (FE0000) 16 MEG

	CMP	BYTE PTR DS:(ES_TEMP.BASE_HI_BYTE),0FEH ; TOP OF MEMORY?
	JE	KB_LOOP3				; EXIT NEXT TEST IF DONE

;-----	SET ES AND DS REGISTERS TO MEMORY BLOCK

	PUSH	BYTE PTR DS_TEMP
	POP	DS
	PUSH	BYTE PTR ES_TEMP
	POP	ES

	MOV	AL,31H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  31 <><>

	MOV	CX,8000H		; SET COUNT FOR 32K WORDS
	CALL	STGTST_CNT
	JZ	N1			; SKIP IF OK
	JMP	E21A			; GO PRINT ERROR
N1:
	POP	CX			; POP CX TO GET AX
	POP	AX			; RECOVER TESTED MEMORY

;-----	WRITE THE CURRENT SIZE FOR (ADDRESS LINES 23-17 TEST) USED LATER

	SUB	DI,DI			; POINT TO BEGINNING OR A BLOCK
	STOSW				; WRITE THE CURRENT SIZE
					;  AT THE STARTING ADDRESS
	ADD	AX,64			; ADVANCE COUNT TO NEXT BLOCK
	PUSH	AX			; SAVE TESTED MEMORY
	PUSH	CX			; SAVE LOOP COUNT

	CALL	PRT_OK			; DISPLAY "0XXXX OK" MESSAGE
	POP	CX			; RECOVER 64K BLOCK COUNT
	DEC	CX			; DECREMENT BLOCK COUNT FOR LOOP
	JCXZ	KB_LOOP3		; CONTINUE TO NEXT TEST IF DONE

	PUSH	CX			; SAVE LOOP COUNT
	JMP	E21			; LOOP TILL ALL MEMORY CHECKED

KB_LOOP3:				;	END MAIN TEST LOOP
	POP	AX			; CLEAR MAXIMUM BLOCK COUNT
	POP	AX			; CLEAR BASE SIZE COUNT FROM STACK
					; ADDRESS TEST VALUES ARE IN STACK
;-----	ADDRESS LINE 16-23 TEST
					;	LET FIRST PASS BE SEEN
	MOV	CX,16571		; COUNT FOR 250 MS FIXED TIME DELAY
	CALL	WAITF			; ALLOW SIX DISPLAY REFRESH CYCLES

;-----	INITIALIZE DS DESCRIPTOR

	PUSH	BYTE PTR GDT_PTR
	POP	ES
	MOV	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),0
	MOV	ES:DS_TEMP.BASE_LO_WORD,0

;-----	TEMPORARY SEGMENT SAVE IN DMA PAGE REGISTER

	SUB	AL,AL
	OUT	DMA_PAGE+4,AL		; HIGH BYTE OF LOW WORD OF SEGMENT
	OUT	DMA_PAGE+5,AL		; LOW BYTE OF LOW WORD OF SEGMENT
	MOV	AL,01H			; SET HIGH BYTE OF SEGMENT WORD
	OUT	DMA_PAGE+3,AL		; HIGH BYTE OF SEGMENT

;-----	POINT TO NEXT BLOCK OF 64K

E21_A:
	MOV	AL,33H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  33 <><>
	ADD	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),01

;-----	CHECK FOR END OF BASE MEMORY TO BE TESTED

	CMP	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),0AH
	JA	NEXT_A			; CONTINUE IF ABOVE 1 MEG

	POP	CX			; GET COUNT
	POP	BX			; GET COUNT TESTED
	POP	AX			; RECOVER COUNT OF BASE MEMORY BLOCKS
	PUSH	AX			; SAVE BASE COUNT
	PUSH	BX			; SAVE TESTED COUNT
	PUSH	CX			; SAVE TOTAL COUNT
	CMP	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),AL		; MAX BASE COUNT
	JB	NEXT_A			; CONTINUE IF NOT DONE WITH BASE MEMORY

;-----	DO ADDITIONAL STORAGE ABOVE 1 MEG

NEXT_A2:
	MOV	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),10H
NEXT_A:
	MOV	AL,BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE)

;-----	DMA PAGE REGISTERS 3
					; SAVE THE HIGH BYTE OF SEGMENT
	OUT	DMA_PAGE+3,AL		;  FOR POSSIBLE ERROR

;-----	CHECK FOR TOP OF MEMORY (FE0000) 16 MEG

	CMP	AL,0FEH 		; TOP OF MEMORY?
	JZ	KB_LOOP_3		; GO NEXT TEST IF IT IS

;-----	SET DS REGISTER

	PUSH	BYTE PTR DS_TEMP
	POP	DS
	SUB	DI,DI			; POINT TO START OF BLOCK
	MOV	DX,DS:[DI]		; GET THE VALUE OF THIS BLOCK
	MOV	SI,DI			; SET SI FOR POSSIBLE ERROR
	SUB	AX,AX			; CLEAR MEMORY LOCATION
	MOV	[DI],AX

;-----	ALLOW DISPLAY TIME TO DISPLAY MESSAGE AND REFRESH TO RUN

	MOV	CX,6761 		; COUNT FOR 102 MS FIXED TIME DELAY
	CALL	WAITF			; ALLOW FIVE DISPLAY REFRESH CYCLES
	POP	CX			; GET THE LOOP COUNT
	POP	AX			; RECOVER TESTED MEMORY
	PUSH	AX			; SAVE TESTED MEMORY
	PUSH	CX			; SAVE LOOP COUNT
	CMP	AX,DX			; DOES THE BLOCK ID MATCH
	MOV	AX,DX			; GET THE BLOCK ID FOR POSSIBLE ERROR
	JNZ	E21A			; GO PRINT ERROR

;-----	CHECK FOR CHECK PARITY

	IN	AL,PORT_B		; CHECK FOR I/O OR PARITY CHECK
	AND	AL,PARITY_ERR		; STRIP UNWANTED BITS
	JNZ	E21A			; EXIT IF PARITY ERROR

	POP	CX			; POP CX TO GET AX
	POP	AX			; RECOVER TESTED MEMORY
	ADD	AX,64			; 64K INCREMENTS
	PUSH	AX			; SAVE TESTED MEMORY
	PUSH	CX			; SAVE LOOP COUNT
	CALL	PRT_OK			; DISPLAY OK MESSAGE
	POP	CX			; RECOVER 64K BLOCK COUNT
	DEC	CX			; LOOP TILL ALL MEMORY CHECKED
	JCXZ	KB_LOOP_3		; CONTINUE

	PUSH	CX			; SAVE LOOP COUNT
	JMP	E21_A			; CONTINUE TILL DONE

;-----	BACK TO REAL MODE - MEMORY TESTS DONE

KB_LOOP_3:
	MOV	AL,34H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  34 <><>
					; BACK TO REAL MODE
	JMP	PROC_SHUTDOWN		; NEXT TEST VIA JUMP TABLE (SHUT2)


;-----	PRINT FAILING ADDRESS AND XOR'ED PATTERN IF DATA COMPARE ERROR
;-----	USE DMA PAGE REGISTERS AS TEMPORARY SAVE AREA FOR ERROR
;	SET SHUTDOWN 3

E21A:	OUT	DMA_PAGE+1,AL		; SAVE FAILING BIT PATTERN (LOW BYTE)
	MOV	AL,AH			; SAVE HIGH BYTE
	OUT	DMA_PAGE+2,AL
	MOV	AX,SI			; GET THE FAILING OFFSET
	OUT	DMA_PAGE+5,AL
	XCHG	AH,AL
	OUT	DMA_PAGE+4,AL

;-----	CLEAR I/O CHANNEL CHECK OR R/W PARITY CHECK

	SUB	SI,SI			; WRITE TO FAILING BLOCK
	STOSW
	IN	AL,PORT_B		; GET PARITY CHECK LATCHES
	OUT	DMA_PAGE+7,AL		; SAVE FOR ERROR HANDLER
	OR	AL,RAM_PAR_OFF		; TOGGLE I/O-PARITY CHECK ENABLE
	OUT	PORT_B,AL		;  TO RESET CHECKS
	AND	AL,RAM_PAR_ON
	OUT	PORT_B,AL

;-----	GET THE LAST OF GOOD MEMORY

	POP	AX			; CLEAR BLOCK COUNT
	POP	AX			; GET THE LAST OF GOOD MEMORY
	POP	BX			; GET BASE MEMORY COUNTER
	SHL	BX,6			; CONVERT TO MEMORY SIZE COUNTS
	SUB	AX,BX			; COMPARE LAST GOOD MEMORY WITH BASE
	JAE	E211			; IF ABOVE OR EQUAL, USE REMAINDER IN
					;  CMOS_U_M_S_(H/L)
;-----	ELSE SET BASE MEMORY SIZE

	PUSH	BYTE PTR RSDA_PTR	; SET THE DATA SEGMENT
	POP	DS			; IN PROTECTED MODE

	ADD	AX,BX			; CONVERT BACK TO LAST WORKING MEMORY
	MOV	@MEMORY_SIZE,AX 	; TO INDICATE HOW MUCH MEMORY WORKING

;-----	RESET 512K --> 640K OPTION IF SET

	MOV	AX,X*(CMOS_INFO128+NMI) ; ADDRESS OPTIONS INFORMATION BYTE
	CALL	CMOS_READ		; READ THE MEMORY INFORMATION FLAG
	AND	AL,NOT M640K		; SET 640K OPTION OFF
	XCHG	AL,AH			; MOVE TO WORK REGISTER
	CALL	CMOS_WRITE		; UPDATE STATUS IF IT WAS ON
	XOR	AX,AX			; CLEAR VALUE FOR EXTENSION MEMORY
E211:
	MOV	CX,AX			; SAVE ADJUSTED MEMORY SIZE
	MOV	AL,CMOS_U_M_S_HI+NMI
	CALL	CMOS_WRITE		; SAVE THE HIGH BYTE MEMORY SIZE
	MOV	AH,CL			; GET THE LOW BYTE
	MOV	AL,CMOS_U_M_S_LO+NMI	; DO THE LOW BYTE
	CALL	CMOS_WRITE		; WRITE IT

;-----	SET SHUTDOWN 3

	MOV	AX,3*H+CMOS_SHUT_DOWN+NMI	; ADDRESS FOR SHUTDOWN RETURN
	CALL	CMOS_WRITE			; SET RETURN 3

;-----	SHUTDOWN

	JMP	PROC_SHUTDOWN
PAGE
;--------------------------------------------------------------------
; MEMORY ERROR REPORTING	(R/W/ MEMORY OR PARITY ERRORS)	    :
;								    :
; DESCRIPTION FOR ERRORS 201 (CMP ERROR OR PARITY)		    :
;		      OR 202 (ADDRESS LINE 0-15 ERROR)		    :
;								    :
;	"AABBCC DDEE 201" (OR 202)                                  :
;			  AA=HIGH BYTE OF 24 BIT ADDRESS	    :
;			  BB=MIDDLE BYTE OF 24 BIT ADDRESS	    :
;			  CC=LOW BYTE OF 24 BIT ADDRESS 	    :
;			  DD=HIGH BYTE OF XOR FAILING BIT PATTERN   :
;			  EE=LOW BYTE OF XOR FAILING BIT PATTERN    :
;								    :
; DESCRIPTION FOR ERROR 202 (ADDRESS LINE 00-15)		    :
;	A WORD OF FFFF IS WRITTEN AT THE FIRST WORD AND LAST WORD   :
;	OF EACH 64K BLOCK WITH ZEROS AT ALL OTHER LOCATIONS OF THE  :
;	BLOCK.	A SCAN OF THE BLOCK IS MADE TO INSURE ADDRESS LINE  :
;	0-15 ARE FUNCTIONING.					    :
;								    :
; DESCRIPTION FOR ERROR 203 (ADDRESS LINE 16-23)		    :
;	AT THE LAST PASS OF THE STORAGE TEST, FOR EACH BLOCK OF     :
;	64K, THE CURRENT STORAGE SIZE (ID) IS WRITTEN AT THE FIRST  :
;	WORD OF EACH BLOCK. IT IS USED TO FIND ADDRESSING FAILURES. :
;								    :
;	"AABBCC DDEE 203"                                           :
;			 SAME AS ABOVE EXCEPT FOR DDEE		    :
;								    :
; GENERAL DESCRIPTION FOR BLOCK ID (DDEE WILL NOW CONTAINED THE ID) :
;	DD=HIGH BYTE OF BLOCK ID				    :
;	EE=LOW BYTE OF BLOCK ID 				    :
;								    :
;	BLOCK ID       ADDRESS RANGE				    :
;	0000	       000000 --> 00FFFF			    :
;	0040	       010000 --> 01FFFF			    :
;	//							    :
;	0200	       090000 --> 09FFFF (512->576K) IF 640K BASE   :
;		       100000 --> 10FFFF (1024->1088K) IF 512K BASE :
;								    :
; EXAMPLE (640K BASE MEMORY + 512K I/O MEMORY = 1152K TOTAL)	    :
;	NOTE: THE CORRECT BLOCK ID FOR THID FAILURE IS 0280 HEX,    :
;	      DUE TO AN ADDRESS FAILURE THE BLOCK ID+128K OVERLAYED :
;	      THE CORRECT BLOCK ID.				    :
;								    :
;	00640K OK	 <-- LAST OK MEMORY			    :
;	10000 0300 202	 <-- ERROR DUE TO ADDRESS FAILURE	    :
;								    :
; IF A PARITY LATCH WAS SET, THE CORRESPONDING MESSAGE WILL DISPLAY.:
;								    :
;	"PARITY CHECK 1" (OR 2)                                     :
;								    :
; DMA PAGE REGISTERS ARE USED AS TEMPORARY SAVE AREAS FOR SEGMENT   :
; DESCRIPTOR VALUES.						    :
;--------------------------------------------------------------------

SHUT3:					;	ENTRY FROM PROCESSOR SHUTDOWN 3
	CALL	DDS			; SET REAL MODE DATA SEGMENT

					;	<><> MEMORY FAILED  <><>
	MOV	@MFG_ERR_FLAG+1,MEM_FAIL; CLEAR AND SET MANUFACTURING ERROR FLAG
	MOV	AL,CR			; CARRIAGE RETURN
	CALL	PRT_HEX
	MOV	AL,LF			; LINE FEED
	CALL	PRT_HEX
	IN	AL,DMA_PAGE+3		; GET THE HIGH BYTE OF 24 BIT ADDRESS
	CALL	XPC_BYTE		; CONVERT AND PRINT CODE
	IN	AL,DMA_PAGE+4		; GET THE MIDDLE BYTE OF 24 BIT ADORES
	CALL	XPC_BYTE
	IN	AL,DMA_PAGE+5		; GET THE LOW BYTE OF 24 BIT ADDRESS
	CALL	XPC_BYTE
	MOV	AL,' '                  ; SPACE TO MESSAGE
	CALL	PRT_HEX
	IN	AL,DMA_PAGE+2		; GET HIGH BYTE FAILING BIT PATTERN
	CALL	XPC_BYTE		; CONVERT AND PRINT CODE
	IN	AL,DMA_PAGE+1		; GET LOW BYTE FAILING BIT PATTERN
	CALL	XPC_BYTE		; CONVERT AND PRINT CODE

;-----	CHECK FOR ADDRESS ERROR

	IN	AL,MFG_PORT		; GET THE CHECKPOINT
	CMP	AL,33H			; IS IT AN ADDRESS FAILURE?
	MOV	SI,OFFSET E203		; LOAD ADDRESS ERROR 16->23
	JZ	ERR2			; GO IF YES

	MOV	SI,OFFSET E202		; LOAD ADDRESS ERROR 00->15
	CMP	AL,32H			; GO IF YES
	JZ	ERR2

	MOV	SI,OFFSET E201		; SETUP ADDRESS OF ERROR MESSAGE
ERR2:
	CALL	E_MSG			; PRINT ERROR MESSAGE
	IN	AL,DMA_PAGE+7		; GET THE PORT_B VALUE

;-----	DISPLAY "PARITY CHECK ?" ERROR MESSAGES

	TEST	AL,PARITY_CHECK 	; CHECK FOR PLANAR ERROR
	JZ	NMI_M1			; SKIP IF NOT

	PUSH	AX			; SAVE STATUS
	CALL	PADING			; INSERT BLANKS
	MOV	SI,OFFSET D1		; PLANAR ERROR, ADDRESS "PARITY CHECK"
	CALL	P_MSG			; DISPLAY "PARITY CHECK 1" MESSAGE
	POP	AX			; AND RECOVER STATUS
NMI_M1:
	TEST	AL,IO_CHECK		; I/O PARITY CHECK?
	JZ	NMI_M2			; SKIP IF CORRECT ERROR DISPLAYED

	CALL	PADING			; INSERT BLANKS
	MOV	SI,OFFSET D2		; ADDRESS OF "PARITY CHECK 2" MESSAGE
	CALL	P_MSG			; DISPLAY "PARITY CHECK 2" ERROR
NMI_M2:
					; CONTINUE TESTING SYSTEM ....
PAGE
;-----	ENTRY FROM SHUTDOWN

SHUT2:

;--------------------------------------------------------
; TEST.20						:
;	ADDITIONAL PROTECTED (VIRTUAL MODE) TEST	:
; DESCRIPTION						:
;	THE PROCESSOR IS PUT IN PROTECTED MODE AND	:
;	THE FOLLOWING FUNCTIONS ARE VERIFIED		:
;							:
;	1. VERIFY PROTECTED MODE			:
;	   THE MACHINE STATUS IS CHECK FOR VIRTUAL MODE :
;	2. PROGRAMMED INTERRUPT TEST			:
;	   AN PROGRAMMED INTERRUPT 32 IS ISSUED AND	:
;	   AND VERIFIED 				:
;	3. EXCEPTION INTERRUPT 13 TEST			:
;	   A DESCRIPTOR SEGMENT LIMIT IS SET TO ZERO	:
;	   AND A WRITE TO THAT SEGMENT IS ATTEMPTED	:
;	   AN EXCEPTION 13 IS EXPECTED AND VERIFIED	:
;	4. LDT/SDT LTR/STR TEST 			:
;	   LOAD LDT REGISTER AND VERIFY CORRECT 	:
;	   LOAD TASK REGISTER AND VERIFY CORRECT	:
;	   THEY ARE VERIFIED VIA THE STORE INSTRUCTION	:
;	5. THE CONTROL FLAGS OF THE 286 FOR DIRECTION	:
;	   ARE VERIFIED VIA THE STD AND CLD COMMANDS	:
;	   IN PROTECTED MODE				:
;	6. BOUND INSTRUCTION TEST (EXCEPTION INT 5)	:
;	   CREATE A SIGNED ARRAY INDEX WITHIN AND	:
;	   OUTSIDE THE LIMITS.	CHECK THAT NO EXC INT	:
;	   IF WITHIN LIMIT AND THAT AN EXC INT 5	:
;	   OCCURS IF OUTSIDE THE LIMITS.		:
;	7. PUSH ALL POP ALL TEST			:
;	   SET GENERAL PURPOSE REGISTERS TO DIFFERENT	:
;	   VALUES, ISSUE A PUSH ALL, CLEAR THE REGISTERS:
;	   THEN ISSUE A POP ALL AND VERIFY CORRECT.	:
;	8. CHECK THE VERR/VERW INSTRUCTIONS		:
;	   THE ACCESS BYTE IS SET TO READ ONLY THEN TO	:
;	   A WRITE ONLY AND THE VERR/VERW INSTRUCTIONS	:
;	   ARE VERIFIED.				:
;	9. CAUSE AN INTERRUPT 13 VIA A WRITE TO A	:
;	   READ ONLY SEGMENT				:
;      10. VERIFY THE ARPL INSTRUCTION FUNCTIONS	:
;	   SET THE RPL FIELD OF A SELECTOR AND		:
;	   VERIFY THAT CURRENT SELECTOR RPL IS SET	:
;	   CORRECTLY.					:
;      11. VERIFY THE LAR INSTRUCTION FUNCTIONS 	:
;      12. VERIFY THE LSL INSTRUCTION FUNCTIONS 	:
;      13. LOW MEG CHIP SELECT TEST			:
;--------------------------------------------------------

	JMP	POST3			; GO TEST THE 286 PROTECTED MODE

;-----	FAILURE ENTRY FROM A SHUTDOWN

SHUT7:	CALL	DDS			; ESTABLISH THE DATA SEGMENT
	IN	AL,MFG_PORT		; CHECK FOR CHIP SELECT ERROR
	CMP	AL,35H
	MOV	SI,OFFSET E109		; PRINT ERROR 109
	JZ	SHUT7B			; GO IF NOT
SHUT7A: MOV	SI,OFFSET E104		; PROTECTED MODE FAILED

	OR	@MFG_ERR_FLAG+1,PRO_FAIL;	<><><><><><><><><><><><><><><>
					;	<><> VIRTUAL MODE FAILED  <><>

	CALL	E_MSG			; PRINT MESSAGE
	JMP	SHORT SHUT6
SHUT7B: CALL	E_MSG			; PRINT MESSAGE

	OR	@MFG_ERR_FLAG+1,LMCS_FAIL;	<><><><><><><><><><><><><><><>
					;	<><> LOW MEG CHIP SELECT  <><>

;-----	PROTECTED MODE TEST PASSED ENTRY FROM A SHUTDOWN

SHUT6:	CALL	DDS			; PROTECTED MODE TEST PASSED
	SUB	AX,AX			; CLEAR KEYBOARD STATE FLAGS
	MOV	WORD PTR @KB_FLAG,AX
	MOV	CX,0EH			; CLEAR PAGE REGISTERS
	MOV	DX,DMA_PAGE+1
CLR_LOOP:
	SUB	AL,AL
	OUT	DX,AL
	INC	DX
	LOOP	CLR_LOOP

;------------------------------------------------
;TEST.21					:
;      KEYBOARD TEST				:
; DESCRIPTION					:
;      RESET THE KEYBOARD AND CHECK THAT SCAN	:
;      CODE "AA" IS RETURNED TO THE PROCESSOR.  :
;      CHECK FOR STUCK KEYS.			:
;------------------------------------------------

	MOV	AL,35H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  35 <><>

	TEST	@MFG_TST,MFG_LOOP	; MANUFACTURING BURN IN TEST MODE?
	JNZ	F7_A
	JMP	F7			; YES - SKIP KEYBOARD TEST
F7_A:	CMP	BYTE PTR @RESET_FLAG,064H ; MANUFACTURING RUN IN MODE?
	JNZ	F7_B
	JMP	F7			; YES - SKIP KEYBOARD TEST
F7_B:	MOV	AL,36H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  36 <><>
	CLI
	CMP	@RESET_FLAG,1234H	; SOFT RESET?
	JZ	G10
	CMP	BYTE PTR @RESET_FLAG,KB_OK ; CHECK FOR AA ALREADY RECEIVED
	JZ	G10			; GO IF YES
	MOV	AL,ENA_KBD
	CALL	C8042			; ENABLE KEYBOARD
	MOV	BH,4			; TRY 4 TIMES
LOOP1:	CALL	OBF_42			; CHECK FOR OUTPUT BUFFER FULL
	JNZ	G10			; GO IF BUFFER FULL
	DEC	BH
	JNZ	LOOP1
G10:	MOV	AL,DIS_KBD		; DISABLE KEYBOARD
	CALL	C8042
	IN	AL,PORT_A		; FLUSH
	MOV	AL,KYBD_CLK_DATA	; GET THE CLOCK AND DATA LINES
	CALL	C8042
	CALL	OBF_42			; WAIT FOR OUTPUT BUFFER FULL
	IN	AL,PORT_A		; GET THE RESULTS
	TEST	AL,KYBD_CLK		; KEYBOARD CLOCK MUST BE LOW
	JZ	G11

	OR	@MFG_ERR_FLAG+1,KYCLK_FAIL ;	<><><><><><><><><><><><><><><>
					;	<><> KEYBOARD CLOCK HIGH  <><>
	MOV	SI,OFFSET E304		; DISPLAY 304 ERROR
	JMP	SHORT F6D		; REPORT ERROR
G11:	CALL	KBD_RESET		; ISSUE RESET TO KEYBOARD
	JCXZ	F6			; PRINT ERROR MESSAGE IF NO INTERRUPT
	MOV	AL,37H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  37 <><>
	CMP	BL,KB_OK		; SCAN CODE AS EXPECTED?
	JNE	F6			; NO - DISPLAY ERROR MESSAGE

;-----	CHECK FOR STUCK KEYS

	MOV	AL,38H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  38 <><>

	MOV	AL,ENA_KBD		; ASSURE KEYBOARD ENABLED
	CALL	C8042			; ISSUE THE COMMAND
	MOV	CX,6628 		; COUNT FOR 100 MILLISECONDS
	CALL	WAITF			; DELAY FOR A WHILE
	IN	AL,STATUS_PORT		; CHECK FOR STUCK KEYS
	TEST	AL,OUT_BUF_FULL 	; OUT BUFFER FULL?
	JE	F7			; YES - CONTINUE TESTING

	MOV	AL,39H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  39 <><>

	IN	AL,PORT_A		; GET THE SCAN CODE
	CALL	XPC_BYTE		; CONVERT AND PRINT
	JMP	SHORT F6C		; CONTINUE

;-----	KEYBOARD ERROR TRY TO DETERMINE IF 8042 INTERFACE IS WORKING

F6:	CLI
	MOV	AL,INTR_FACE_CK 	; COMMAND TO 8042
	OUT	STATUS_PORT,AL
	SUB	CX,CX
	MOV	BH,05			; WAIT FOR OUTPUT BUFFER FULL
F6A:	IN	AL,STATUS_PORT
	TEST	AL,OUT_BUF_FULL 	; 8042 FINISHED TEST?
	LOOPZ	F6A
	JNZ	F6B			; GO CHECK RESULTS
	DEC	BH
	JNZ	F6A			; TRY AGAIN
	MOV	SI,OFFSET E303		; INDICATE PLANAR FAILURE
	JMP	SHORT F6D		; (REMOVE KEYBOARD TRY AGAIN)
F6B:	IN	AL,PORT_A		; GET THE RESULTS OF INTERFACE TEST
	CMP	AL,0			; IS THE INTERFACE OK?
	JZ	F6C
	OR	@MFG_ERR_FLAG+1,KY_SYS_FAIL ;	<><><><><><><><><><><><><>
					;	<><> KEYBOARD/SYSTEM  <><>
	MOV	SI,OFFSET E303		; PLANAR FAILURE
	JMP	SHORT F6D		; GO IF YES
F6C:	MOV	SI,OFFSET E301		; GET MESSAGE.ADDR

	OR	@MFG_ERR_FLAG+1,KYBD_FAIL;	<><><><><><><><><><><><><>
					;	<><> KEYBOARD FAILED  <><>

F6D:	CALL	E_MSG			; PRINT MESSAGE ON SCREEN

;-----	INITIALIZE 8042 TO HONOR KEY LOCK

F7:	MOV	AL,3AH			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  3A <><>

	MOV	AL,0FFH 		; DISABLE INTERRUPTS
	OUT	INTA01,AL
	CLI
	MOV	AL,WRITE_8042_LOC	; WRITE 8042 MEMORY COMMAND
	CALL	C8042			; ISSUE THE COMMAND
	MOV	AL,45H			; SET SYSTEM FLAG - OUTBUF INTERRUPT
	OUT	PORT_A,AL		; PC COMPATIBILITY
					; RESET INHIBIT OVER RIDE
;-----	DEGATE ADDRESS LINE 20

	MOV	AH,DISABLE_BIT20	; SET COMMAND IN AH
	CALL	GATE_A20		; ISSUE THE COMMAND

;-----	SETUP HARDWARE INTERRUPT VECTOR TABLE LEVEL 0-7

	SUB	AX,AX
	MOV	ES,AX
	MOV	CX,08			; GET VECTOR COUNT
	PUSH	CS			; SETUP DS SEGMENT REGISTER
	POP	DS
	MOV	SI,OFFSET VECTOR_TABLE
	MOV	DI,OFFSET @INT_PTR
F7A:	MOVSW
	INC	DI			; SKIP OVER SEGMENT
	INC	DI
	LOOP	F7A

;-----	SETUP HARDWARE INTERRUPT VECTORS LEVEL 8-15 (VECTORS START AT INT 70H)

	ASSUME ES:ABS0
	SUB	AX,AX
	MOV	ES,AX
	MOV	CX,08			; GET VECTOR COUNT
	PUSH	CS			; SETUP DS SEGMENT REGISTER
	POP	DS
	MOV	SI,OFFSET SLAVE_VECTOR_TABLE
	MOV	DI,OFFSET @SLAVE_INT_PTR
F7A1:	MOVSW
	INC	DI			; SKIP OVER SEGMENT
	INC	DI
	LOOP	F7A1

;-----	SET UP OTHER INTERRUPTS AS NECESSARY

	ASSUME	DS:ABS0
	SUB	AX,AX			; DS=0
	MOV	DS,AX
	MOV	WORD PTR @NMI_PTR,OFFSET NMI_INT ; NMI INTERRUPT
	MOV	WORD PTR @INT5_PTR,OFFSET PRINT_SCREEN	; PRINT SCREEN
	MOV	WORD PTR @BASIC_PTR+2,0F600H	 ; SEGMENT FOR CASSETTE BASIC
	MOV	WORD PTR @EXT_PTR+2,0	; SEGMENT FOR GRAPHIC CHARS 128 - 255

;-----	ZERO RESERVED VECTORS

	MOV	DI,60H*4		; FILL INTERRUPT 60 THRU 67 WITH ZERO
	MOV	CX,16			; CLEAR 16 WORDS
F7A2:	MOV	WORD PTR DS:[DI],0
	ADD	DI,2			; POINT TO NEXT LOCATION
	LOOP	F7A2

;-----	SETUP TIMER 0 TO BLINK LED IF MANUFACTURING TEST MODE

	ASSUME	DS:DATA
	CALL	DDS			; ESTABLISH DATA SEGMENT

	TEST	@MFG_TST,MFG_LOOP	; MFG. TEST MODE?
	JNZ	F9
	MOV	WORD PTR ES:@INT_PTR,OFFSET BLINK_INT ; SETUP TIMER TO BLINK LED
	MOV	AL,0FEH 		; ENABLE TIMER INTERRUPT
	OUT	INTA01,AL
F9:	STI				; ALLOW INTERRUPTS

;-----	ISSUE A RESET TO THE HARD FILE IF SOFT RESET

	CMP	@RESET_FLAG,1234H	; SOFT RESET?
	JNZ	F9A			; CONTINUE IF NOT
	MOV	CX,0FFH
	MOV	DX,03F6H
	MOV	AL,04H			; RESET
	OUT	DX,AL
F9_A:	LOOP	F9_A			; HOLD RESET
	SUB	AL,AL
	OUT	DX,AL			; REMOVE RESET

;----------------------------------------------------------------
; TEST.23							:
;	DISKETTE ATTACHMENT TEST				:
; DESCRIPTION							:
;	CHECK IF IPL DISKETTE DRIVE IS ATTACHED TO SYSTEM, IF	:
;	ATTACHED, VERIFY STATUS OF NEC FDC AFTER A RESET. ISSUE :
;	A RECALIBRATE AND SEEK COMMAND TO FDC AND CHECK STATUS. :
;	COMPLETE SYSTEM INITIALIZATION THEN PASS CONTROL TO THE :
;	BOOT LOADER PROGRAM.					:
;----------------------------------------------------------------

F9A:	MOV	AL,3CH			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  3C <><>

	MOV	AL,02H			; SET DATA RATE TO 250 K BITS PER SECOND
	MOV	DX,3F7H
	OUT	DX,AL
	TEST	BYTE PTR @EQUIP_FLAG,1H ; DISKETTE PRESENT?
	JZ	F15
	TEST	@MFG_TST,MFG_LOOP	; MFG JUMPER INSTALLED?
	JZ	F15			; GO IF YES
F10:					; DISK_TEST:
	IN	AL,INTA01
	JMP	$+2			; I/O DELAY
	AND	AL,0BFH 		; ENABLE DISKETTE INTERRUPTS
	OUT	INTA01,AL
	MOV	AH,0			; RESET NEC FDC
	MOV	DL,AH			; SET FOR DRIVE 0
	INT	13H			; VERIFY STATUS AFTER RESET
	TEST	AH,0FFH 		; STATUS OK?
	JNZ	F13			; NO - FDC FAILED

;-----	TURN DRIVE 0 MOTOR ON

	MOV	DX,03F2H		; GET ADDRESS OF FDC CARD
	MOV	AL,1CH			; TURN MOTOR ON, ENABLE DMA, INTERRUPTS
	OUT	DX,AL			; WRITE FDC CONTROL REGISTER
	SUB	CX,CX			; WAITF COUNT FOR 0.988 SECONDS
	CALL	WAITF			; WAIT 1 SECOND FOR MOTOR

	XOR	DI,DI			; SELECT DRIVE 0
	MOV	CH,1			; SELECT TRACK 1
	MOV	@SEEK_STATUS,0		; INSURE RECALIBRATE
	OR	@RTC_WAIT_FLAG,01	; NO REAL TIME CLOCK, USE WAIT LOOP
	CALL	SEEK			; RECALIBRATE DISKETTE
	JC	F13			; GO TO ERR SUBROUTINE IF ERR
	MOV	CH,34			; SELECT TRACK 34
	CALL	SEEK			; SEEK TO TRACK 34
	JNC	F14			; OK, TURN MOTOR OFF
F13:					; DSK_ERR:
	OR	@MFG_ERR_FLAG+1,DSK_FAIL;	<><><><><><><><><><><><><>
					;	<><> DISKETTE FAILED  <><>
	MOV	SI,OFFSET E601		; GET ADDRESS OF MESSAGE
	CALL	E_MSG			; GO PRINT ERROR MESSAGE

;-----	TURN DRIVE 0 MOTOR OFF

F14:					; DR0_OFF:
	AND	@RTC_WAIT_FLAG,0FEH	; ALLOW FOR RTC WAIT
	MOV	AL,0CH			; TURN DRIVE 0 MOTOR OFF
	MOV	DX,03F2H		; FDC CONTROLLER ADDRESS
	OUT	DX,AL

;-----	SETUP KEYBOARD PARAMETERS

F15:	MOV	@INTR_FLAG,00H		; SET STRAY INTERRUPT FLAG = 00
	MOV	SI,OFFSET @KB_BUFFER	; SETUP KEYBOARD PARAMETERS
	MOV	@BUFFER_HEAD,SI
	MOV	@BUFFER_TAIL,SI
	MOV	@BUFFER_START,SI
	ADD	SI,32			; DEFAULT BUFFER OF 32 BYTES
	MOV	@BUFFER_END,SI

;-----	SET PRINTER TIMEOUT DEFAULT

	MOV	DI,OFFSET @PRINT_TIM_OUT; SET DEFAULT PRINTER TIMEOUT
	PUSH	DS
	POP	ES
	MOV	AX,1414H		; DEFAULT=20
	STOSW
	STOSW

;-----	SET RS232 DEFAULT

	MOV	AX,0101H		; RS232 DEFAULT=01
	STOSW
	STOSW

;-----	ENABLE TIMER INTERRUPTS

	IN	AL,INTA01
	AND	AL,0FEH 		; ENABLE TIMER INTERRUPTS
	JMP	$+2			; I/O DELAY
	OUT	INTA01,AL

;-----	CHECK CMOS BATTERY AND CHECKSUM

	TEST	@MFG_TST,MFG_LOOP	; MFG JUMPER?
	JNZ	B1_OK			; GO IF NOT
	JMP	F15C			; BYPASS IF YES
B1_OK:
	MOV	AL,CMOS_DIAG+NMI	; ADDRESS DIAGNOSTIC STATUS BYTE
	CALL	CMOS_READ		; READ IT FROM CMOS

	MOV	SI,OFFSET E161		; LOAD BAD BATTERY MESSAGE 161
	TEST	AL,BAD_BAT		; BATTERY BAD?
	JNZ	B1_ER			; DISPLAY ERROR IF BAD

	MOV	SI,OFFSET E162		; LOAD CHECKSUM BAD MESSAGE 162
	TEST	AL,BAD_CKSUM+BAD_CONFIG ; CHECK FOR CHECKSUM OR NO DISKETTE
	JZ	C_OK			; SKIP AND CONTINUE TESTING CMOS CLOCK
B1_ER:
	CALL	E_MSG			; ELSE DISPLAY ERROR MESSAGE
	OR	BP,08000H		; FLAG "SET SYSTEM OPTIONS" DISPLAYED
	JMP	SHORT H_OK1A		; SKIP CLOCK TESTING IF ERROR

;-----	TEST CLOCK UPDATING

C_OK:	MOV	BL,04H			; OUTER LOOP COUNT
D_OK:	SUB	CX,CX			; INNER LOOP COUNT
E_OK:	MOV	AL,CMOS_REG_A+NMI	; GET THE CLOCK UPDATE BYTE
	CALL	CMOS_READ
	TEST	AL,80H			; CHECK FOR UPDATE IN PROGRESS
	JNZ	G_OK			; GO IF YES
	LOOP	E_OK			; TRY AGAIN
	DEC	BL			; DEC OUTER LOOP
	JNZ	D_OK			; TRY AGAIN
F_OK:	MOV	SI,OFFSET E163		; PRINT MESSAGE
	CALL	E_MSG

;-----	SET CMOS DIAGNOSTIC STATUS TO 04 (CLOCK ERROR)

	MOV	AX,X*CMOS_DIAG+NMI	; SET CLOCK ERROR
	CALL	CMOS_READ		; GET THE CURRENT STATUS
	OR	AL,CMOS_CLK_FAIL	; SET NEW STATUS
	XCHG	AL,AH			; GET STATUS ADDRESS AND SAVE NEW STATUS
	CALL	CMOS_WRITE		; MOVE NEW DIAGNOSTIC STATUS TO CMOS
	JMP	SHORT H_OK		; CONTINUE

;-----	CHECK CLOCK UPDATE

G_OK:	MOV	CX,800			; LOOP COUNT
I_OK:	MOV	AL,CMOS_REG_A+NMI	; CHECK FOR OPPOSITE STATE
	CALL	CMOS_READ
	TEST	AL,80H
	LOOPNZ	I_OK			; TRY AGAIN
	JCXZ	F_OK			; PRINT ERROR IF TIMEOUT

;-----	CHECK MEMORY SIZE DETERMINED CONFIGURATION

H_OK:
	MOV	AL,CMOS_DIAG+NMI	; GET THE STATUS BYTE
	CALL	CMOS_READ
	TEST	AL,W_MEM_SIZE		; WAS THE CONFIG= MEM_SIZE_DETERMINED?
	JZ	H_OK1A			; GO IF YES

;-----	MEMORY SIZE ERROR

	MOV	SI,OFFSET E164		; PRINT SIZE ERROR
	CALL	E_MSG			; DISPLAY ERROR

;-----	CHECK FOR CRT ADAPTER ERROR

H_OK1A: CMP	@MFG_ERR_FLAG,0CH	; CHECK FOR MONOCHROME CRT ERROR
	MOV	SI,OFFSET E401		; LOAD MONOCHROME CRT ERROR
	JZ	H_OK1B			; GO IF YES

	CMP	@MFG_ERR_FLAG,0DH	; CHECK FOR COLOR CRT ADAPTER ERROR
	JNZ	J_OK			; CONTINUE IF NOT
	MOV	SI,OFFSET E501		; CRT ADAPTER ERROR MESSAGE
H_OK1B:
	CALL	E_MSG

;-----	CHECK FOR MULTIPLE DATA RATE CAPABILITY

J_OK:
	MOV	DX,03F1H		; D/S/P DIAGNOSTIC REGISTER
	IN	AL,DX			; READ D/S/P TYPE CODE
	AND	AL,11111000B		; KEEP ONLY UNIQUE CODE FOR D/S/P
	CMP	AL,01010000B		; D/S/P CARD - MULTIPLE DATA RATE?
	JZ	J_OK3			; IF SO JUMP

	MOV	DX,05F7H		; FIXED DISK DIAGNOSTIC REGISTER
	IN	AL,DX			; READ FIXED DISK TYPE CODE
	AND	AL,11110000B		; KEEP ONLY UNIQUE CODE FOR F/D
	CMP	AL,10100000B		; FIXED DISK ADAPTER ?
	JZ	J_FAIL			; MUST BE COMBO ELSE ERROR

	MOV	BL,0FH			; OUTER LOOP COUNT WAIT FOR BUSY OFF
	SUB	CX,CX
	MOV	DX,01F7H		; HARD FILE STATUS PORT
J_OK1:
	IN	AL,DX			; GET THE STATUS
	TEST	AL,080H 		; IS THE CONTROLLER BUSY?
	JZ	J_OK2			; CONTINUE IF NOT
	LOOP	J_OK1			; TRY AGAIN
	DEC	BL			; DECREMENT OUTER LOOP
	JNZ	J_OK1			; TRY AGAIN IF NOT ZERO
	AND	AL,0CH			; BITS 2 & 3 = 0 IF MULTI DATA CAPABLE
	JZ	J_OK3			; GO IF YES
	JMP	SHORT J_FAIL		; NO MULTIPLE DATA RATE CAPABILITY
J_OK2:
	MOV	DX,1F4H 		; VERIFY MULTIPLE DATA RATE CAPABLE
	MOV	AL,055H 		; WRITE TO THE CYLINDER BYTE
	OUT	DX,AL
	JMP	$+2			; I/O DELAY
	IN	AL,DX			; CHECK DATA WRITTEN = DATA READ
	CMP	AL,055H
	JNZ	J_FAIL			; GO IF NOT
	MOV	AL,0AAH 		; WRITE ANOTHER PATTERN
	OUT	DX,AL
	JMP	$+2			; I/O DELAY
	IN	AL,DX
	CMP	AL,0AAH 		; IS DATA PATTERN THE SAME?
	JZ	J_OK3			; GO IF SO

J_FAIL:
	OR	@MFG_ERR_FLAG+1,DSK_FAIL;	<><><><><><><><><><><><><>
					;	<><> DISKETTE FAILED  <><>
	MOV	SI,OFFSET E601		; GET ADDRESS OF MESSAGE
	CALL	E_MSG			; GO PRINT ERROR MESSAGE
	JMP	SHORT F15C		; SKIP SETUP IF ERROR

J_OK3:
	OR	@LASTRATE,DUAL		; TURN ON DSP/COMBO FLAG

;-----	INITIALIZE FLOPPY FOR DRIVE TYPE

	MOV	AL,3DH			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT 3D  <><>
	CALL	DSKETTE_SETUP		; INITIALIZE FLOPPY

;-----	CHECK FOR 2ND DISKETTE DRIVE

	CALL	DDS			; INSURE DATA SEGMENT
	MOV	AH,@DSK_STATE+1 	; GET STATE OF SECOND DRIVE
	OR	AH,AH			; IS THERE A DRIVE 2 ATTACHED?
	JZ	F15C			; SKIP IF NOT
	OR	BYTE PTR @EQUIP_FLAG,40H; ELSE SET SECOND DRIVE INSTALLED
	MOV	AH,0FFH 		; SET TEST MASK FOR DRIVE PRESENT
F15C:
	MOV	AL,CMOS_DIAG+NMI	; GET THE CMOS DIAGNOSTIC STATUS
	CALL	CMOS_READ
	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY/CHECKSUM OK
	JNZ	ROM_SCAN1		; BYPASS DISK SETUP IF NOT

	MOV	AL,CMOS_DISKETTE+NMI	; ADDRESS DISKETTE TYPE BYTE
	CALL	CMOS_READ		; GET DISKETTE TYPES
	AND	AL,00FH 		; LOOK AT SECOND DRIVE TYPE DEFINED
	CMP	AL,AH			; ARE BOTH INDICATORS ZERO
	JE	F15D			; SKIP IF NO SECOND DRIVE

	AND	AL,AH			; ARE BOTH INDICATORS NON-ZERO
	JNZ	F15D			; SKIP IF DRIVE FOUND AND DEFINED

	CALL	CONFIG_BAD		; SET BAD_CONFIG IN CMOS_DIAG

;-----	INITIALIZE HARD FILE
F15D:
	MOV	AL,3EH			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  3E <><>

	MOV	AL,CMOS_DISK+NMI	; INSURE CMOS DEFINES TYPE OF FIXED DISK
	CALL	CMOS_READ
	CMP	AL,0H			; INSURE TYPE IS DEFINED
	JZ	ROM_SCAN1		; BYPASS DISK SETUP IF NOT

	CALL	DISK_SETUP		; INITIALIZE HARD FILE(S)

;-----------------------------------------------------------
; TEST.22						    :
; CHECK FOR OPTIONAL ROM FROM C800->E000 IN 2K BLOCKS	    :
;	(A VALID MODULE HAS '55AA' IN THE FIRST 2 LOCATIONS :
;	LENGTH INDICATOR (LENGTH/512) IN THE 3RD LOCATION   :
;	AND TEST/INIT. CODE STARTING IN THE 4TH LOCATION)   :
;-----------------------------------------------------------
ROM_SCAN1:
	STI				; ALLOW INTERRUPTS
	MOV	AL,3BH			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  3B <><>
	CALL	DDS			; SET REAL MODE DATA SEGMENT
	MOV	AL,10			; LINE FEED ON DISPLAY
	CALL	PRT_HEX
ROM_SCAN:

;-----	SET DMA MASK AND REQUEST REGISTERS

	SUB	AL,AL
	OUT	DMA18+2,AL		; SEND ZERO TO MASK REGISTER
	JMP	$+2
	OUT	DMA18+4,AL		; SEND ZERO TO REQUEST REGISTER
	MOV	DX,0C800H		; SET BEGINNING ADDRESS
ROM_SCAN2:
	MOV	DS,DX
	PUSH	DI			; SAVE WORK REGISTER
	MOV	DI,0AA55H		; GET TEST PATTERN
	SUB	BX,BX			; SET BX=0000
	MOV	AX,[BX] 		; GET 1ST WORD FROM MODULE
	CMP	AX,DI			; = TO ID WORD?
	POP	DI			; RECOVER WORK REGISTER
	JNZ	NEXT_ROM		; PROCEED TO NEXT ROM IF NOT
	CALL	ROM_CHECK		; GO CHECK OUT MODULE
	JMP	SHORT ARE_WE_DONE	; CHECK FOR END OF ROM SPACE
NEXT_ROM:
	ADD	DX,0080H		; POINT TO NEXT 2K ADDRESS
ARE_WE_DONE:
	CMP	DX,0E000H		; AT E0000 YET?
	JL	ROM_SCAN2		; GO CHECK ANOTHER ADD. IF NOT

;-----	TEST FOR KEYBOARD LOCKED

	CALL	DDS			; SET DATA SEGMENT
	IN	AL,STATUS_PORT		; IS KEYBOARD UNLOCKED?
	AND	AL,KYBD_INH
	JZ	KEY1			; NO - SET ERROR FLAGS AND PRINT MESSAGE
	JMP	SHORT KEY10		; GO IF OFF
KEY1:
	OR	@MFG_ERR_FLAG+1,KEY_FAIL;	<><><><><><><><><><><><><><>
					;	<><> KEYBOARD IS LOCKED <><>
	ASSUME	DS:DATA
	MOV	SI,OFFSET E302		; PRINT LOCKED MESSAGE	(302)
	CALL	E_MSG
KEY10:
	;===================
;-----	 SETUP @PRINTER_BASE
	;===================

	MOV	DI,OFFSET F4		; OFFSET OF PRINTER ADDRESS TABLE
	MOV	SI,0
F16:
	MOV	DX,CS:[DI]		; GET PRINTER BASE ADDRESS
	MOV	AL,0AAH 		; WRITE DATA TO PORT A
	OUT	DX,AL
	JMP	$+2			; I/O DELAY
	PUSH	DS			; BUS SETTLING
	IN	AL,DX			; READ PORT A
	POP	DS
	CMP	AL,0AAH 		; DATA PATTERN SAME
	JNE	F17			; NO - CHECK NEXT PRINTER CARD
	MOV	@PRINTER_BASE[SI],DX	; YES - STORE PRINTER BASE ADDRESS
	INC	SI			; INCREMENT TO NEXT WORD
	INC	SI
F17:
	INC	DI			; POINT TO NEXT BASE ADDRESS
	INC	DI
	CMP	DI,OFFSET F4E		; ALL POSSIBLE ADDRESSES CHECKED?
	JNE	F16			; PRT_BASE
	;===========
;-----	 SETUP RS232
	;===========
	MOV	BX,0			; POINTER TO RS232 TABLE
	MOV	DX,3FAH 		; CHECK IF RS232 CARD 1 ATTACHED ?
	IN	AL,DX			; READ INTERRUPT ID REGISTER
	TEST	AL,0F8H
	JNZ	F18
	MOV	@RS232_BASE[BX],3F8H	; SETUP RS232 CARD #1 ADDRESS
	INC	BX
	INC	BX
F18:	MOV	DX,2FAH 		; CHECK IF RS232 CARD 2 ATTACHED
	IN	AL,DX			; READ INTERRUPT ID REGISTER
	TEST	AL,0F8H
	JNZ	F19			; BASE_END
	MOV	@RS232_BASE[BX],2F8H	; SETUP RS232 CARD #2
	INC	BX
	INC	BX
	;=================================================================
;-----	 SET UP @EQUIP_FLAG TO INDICATE NUMBER OF PRINTERS AND RS232 CARDS
	;=================================================================
F19:					; BASE_END:
	MOV	AX,SI			; SI HAS 2* NUMBER OF RS232
	MOV	CL,3			; SHIFT COUNT
	ROR	AL,CL			; ROTATE RIGHT 3 POSITIONS
	OR	AL,BL			; OR IN THE PRINTER COUNT
	MOV	BYTE PTR @EQUIP_FLAG+1,AL	; STORE AS SECOND BYTE

;-----	INSURE CMOS CLOCK HAS VALID HOURS.MINUTES.SECONDS

	CALL	SET_TOD 		; INSURE CMOS CLOCK IS VALID

;-----	ENABLE HARDWARE INTERRUPT IF MATH PROCESSOR (80287)

	MOV	AL,40H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  40 <><>

	MOV	DI,OFFSET @IO_ROM_INIT	; ADDRESS WORK STORAGE LOCATION
	XOR	AX,AX			; CLEAR WORK REGISTER (AH)= 0 (NO 287)
	MOV	WORD PTR [DI],AX	; CLEAR THE WORK LOCATION
	FNINIT				; INITIALIZE THE 80287 WITH NO WAIT
	JMP	$+2			; DELAY
	FNSTCW	WORD PTR [DI]		; WRITE THE CURRENT 80287 CONTROL WORD
	PUSHA				; TIME FOR 80287 TO RESPOND
	POPA
	AND	WORD PTR [DI],01F3FH	; CLEAR UNUSED 80287 BITS
	CMP	WORD PTR [DI],0033FH	; IS THE 80287 INSTALLED?
	JNE	NO_287			; GO IF MATH PROCESSOR IS NOT INSTALLED

	FSTSW	WORD PTR [DI]		; STORE THE STATUS WORD (WITH WAIT)
	PUSHA				; TIME FOR 80287 TO RESPOND
	POPA
	TEST	WORD PTR [DI],0B8BFH	; ALL BITS SHOULD BE OFF (OR ERROR)
	JNZ	NO_287			; GO IF NOT INSTALLED

	IN	AL,INTB01		; GET THE SLAVE INTERRUPT MASK
	AND	AL,0DFH 		; ENABLE 80287 INTERRUPTS
	MOV	AH,002H 		; SET WORK REGISTER FOR 80287 FOUND
	OUT	INTB01,AL
NO_287:
	MOV	AL,BYTE PTR @EQUIP_FLAG ; GET LOW EQUIPMENT FLAG
	AND	AL,002H 		; STRIP OFF OTHER BITS
	CMP	AL,AH			; DOES CMOS MATCH HARDWARE ?
	JE	OK_287			; SKIP IF EQUIPMENT FLAG CORRECT

	XOR	BYTE PTR @EQUIP_FLAG,2H ; ELSE SET 80287 BIT TO CORRECT VALUE
	CALL	CONFIG_BAD		; AND SET THE CONFIGURATION ERROR FLAG
OK_287:
;-----	SET KEYBOARD STATE FLAGS

	MOV	WORD PTR @KB_FLAG,0	; RESET ALL KEYBOARD STATUS FLAGS

;-----	ENABLE KEYBOARD/TIMER INTERRUPTS

	IN	AL,INTA01
	AND	AL,0FCH 		; ENABLE TIMER AND KEYBOARD INTERRUPTS
	JMP	$+2			; I/O DELAY
	OUT	INTA01,AL
	MOV	@MFG_ERR_FLAG,0 	; CLEAR MFG ERROR FLAG

;-----	READ KEYBOARD ID TO INITIALIZE KEYBOARD TYPE AND NUM LOCK STATE

	MOV	@KB_FLAG_3,RD_ID+SET_NUM_LK	; SET READ ID COMMAND FOR KBX
	MOV	AL,KB_READ_ID		; GET THIS SYSTEMS KEYBOARD ID REQUEST
	CALL	SND_DATA		; USE KEYBOARD TRANSMISSION ROUTINE
	MOV	CX,1658 		; SET DELAY COUNT TO 25 MILLISECONDS
	CALL	WAITF			; WAIT FOR READ ID RESPONSE (20 MS)
	AND	@KB_FLAG_3,NOT RD_ID+LC_AB+SET_NUM_LK	; RESET READ ID COMMAND

;-----	CHECK FOR SECOND FIXED DISK PRESENT BUT NOT DEFINED

	CMP	@HF_NUM,2		; CHECK FOR TWO DRIVES DEFINED BY CMOS
	JE	F15G			; SKIP TEST IF TWO DRIVES DEFINED

	MOV	AH,010H 		; GET TEST DRIVE READY COMMAND
	MOV	DL,081H 		; POINT TO SECOND FIXED DISK
	INC	@HF_NUM 		; TELL BIOS IT HAS TWO DRIVES
	INT	13H			; CHECK READY THROUGH BIOS
	DEC	@HF_NUM 		; RESTORE CORRECT COUNT (RETAIN CY)
	JC	F15G			; SKIP IF SECOND DRIVE NOT READY
					;	SECOND DRIVE NOT DEFINED
	CALL	CONFIG_BAD		; SET CONFIGURATION BAD
F15G:
;----------------------------------------
;   TEST FOR ANY ERRORS (BP NOT ZERO)	:
;----------------------------------------

	OR	BP,BP			; CHECK (BP)= NON-ZERO	(ERROR HAPPENED)
	JE	F15A_0			; SKIP PAUSE IF NO ERROR

	CMP	BYTE PTR @RESET_FLAG,64H; MFG RUN IN MODE?
	MOV	DX,2			; 2 SHORT BEEP COUNT FOR ERROR(S)
	JNZ	ERR_WAIT		; GO IF NOT

;-----	MFG RUN IN MODE -> SET ERROR FLAG

	MOV	@MFG_ERR_FLAG,0AAH	; INDICATE ERROR
	IN	AL,STATUS_PORT		; CHECK KEY LOCK STATUS
	AND	AL,KYBD_INH		; IS THE KEYBOARD LOCKED
	JNZ	F15A_0			; CONTINUE MFG MODE IF NOT LOCKED ELSE

	MOV	DX,5			; 5 SHORT BEEPS FOR MFG SETUP ERROR
ERR_WAIT:
	CALL	ERR_BEEP		; BEEPS FOR ERROR(S)
	MOV	AL,CMOS_DIAG		; ADDRESS CMOS
	CALL	CMOS_READ		; GET THE DIAGNOSTIC STATUS BYTE
	TEST	AL,BAD_CONFIG		; CHECK FOR BAD HARDWARE CONFIGURATION
	JZ	ERR_WKEY		; SKIP IF NOT SET

	TEST	BP,08000H		; ELSE CHECK FOR E161/E162 POSTED
	JNZ	ERR_WKEY		; SKIP IF DISPLAYED BEFORE NOW

	MOV	SI,OFFSET E162		; ELSE DISPLAY 'OPTIONS NOT SET'
	CALL	P_MSG			; WITH NON HALTING ROUTINE

;-----	CHECK FOR "UNLOCK SYSTEM UNIT KEYLOCK" MESSAGE REQUIRED

ERR_WKEY:
	IN	AL,STATUS_PORT		; CHECK IF RESUME MESSAGE NEEDED
	AND	AL,KYBD_INH		; IS THE KEYBOARD LOCKED
	JNZ	ERR_WAIT2		; SKIP LOCK MESSAGE IF NOT

	MOV	SI,OFFSET F3D1		; ERROR MESSAGE FOR KEYBOARD LOCKED
	CALL	P_MSG

;-----	DISPLAY '(RESUME = "F1" KEY)' FOR ERRORS

ERR_WAIT2:
	MOV	SI,OFFSET F3D		; RESUME ERROR MESSAGE
	CALL	P_MSG

;-----	INITIALIZE PRINTER  (ALTERNATE DISPLAY DEVICE)

	MOV	AH,1			;
	SUB	DX,DX			; FIRST PRINTER
	INT	17H			;
ERR_WAIT1:
	MOV	AL,3FH			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  3F <><>
	MOV	AH,00
	INT	16H			; WAIT FOR 'F1' KEY
	CMP	AH,3BH
	JNE	ERR_WAIT1
F15A_0:
	TEST	@MFG_TST,MFG_LOOP	; MFG BURN IN MODE
	JNZ	F15A			; GO IF NOT
	JMP	START_1 		; GO LOOP POST
F15A:	CMP	BYTE PTR @RESET_FLAG,64H; MFG RUN IN?
	JZ	F15B			; BYPASS BEEP IF YES

	MOV	DX,1			; 1 SHORT BEEP (NO ERRORS)
	CALL	ERR_BEEP
	;===============
;-----	SET TIME OF DAY
	;===============

F15B:	CALL	SET_TOD

;-----	CLEAR DISPLAY SCREEN

	SUB	AH,AH			; CLEAR FLAGS
	MOV	AL,@CRT_MODE
	INT	10H			; CLEAR SCREEN

;-----	CLEAR DESCRIPTOR TABLES

F20:	MOV	CX,0500 		; CLEAR 1K
	MOV	DI,SYS_IDT_LOC		; POINT ES TO START OF DESCRIPTORS
	SUB	AX,AX
	MOV	ES,AX
F20_A:	MOV	ES:[DI],AX		; CLEAR
	ADD	DI,2			; POINT TO NEXT LOCATION
	LOOP	F20_A			; CONTINUE TILL DONE

;-----	SET POST SYSTEM STACK

	MOV	AX,ABS0 		; GET THE POST STACK SEGMENT
	MOV	SS,AX
	MOV	SP,OFFSET @TOS

;-----	ENSURE THAT MASTER LEVEL 2 ENABLED

	IN	AL,INTA01		; GET THE CURRENT MASK
	AND	AL,0FBH
	JMP	$+2			; I/O DELAY
	OUT	INTA01,AL

;-----	TEST FOR MFG RUN-IN TEST

	CMP	BYTE PTR @RESET_FLAG,64H; IS THE MFG RUN-IN TEST?
	JNZ	END_287 		; GO IF NOT
	JMP	SHORT SHUT4		; BOOT LOAD IF YES

;-----	UNMASK SLAVE HARDWARE INTERRUPT 9 (LEVEL 71)
END_287:
	IN	AL,INTB01		; GET THE CURRENT MASK
	AND	AL,0FDH
	JMP	$+2			; I/O DELAY
	OUT	INTB01,AL		; SET NEW MASK

;------------------------------------------------------------------
; TEST FOR SYSTEM CODE AT SEGMENT E000:0
;   FIRST WORD = AA55H
;   LAST BYTE = CHECKSUM
;   ENTRY POINT = FIRST BYTE + 3
; IF TEST IS SUCCESSFUL A CALL FAR TO THE ENTRY POINT IS EXECUTED
;------------------------------------------------------------------
	MOV	AL,41H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  41 <><>

	MOV	AL,CMOS_REG_D+NMI	; INSURE NMI OFF AND CMOS AT DEFAULT
	OUT	CMOS_PORT,AL

;ENDIF

	MOV	BYTE PTR @RESET_FLAG,0	; CLEAR FLAG
	MOV	AX,0E000H		; SEGMENT OF SYSTEM CODE
	MOV	ES,AX
	SUB	DI,DI
	MOV	AX,ES:[DI]		; CHECK FOR AA55
	PUSH	BX			; BUS SETTLE
	POP	BX
	CMP	AX,0AA55H
	PUSHF				; SAVE FLAGS
	MOV	ES:[DI],AX		; CLEAR POSSIBLE PARITY CHECK
	IN	AL,PORT_B
	OR	AL,RAM_PAR_OFF		; TOGGLE I/O-PARITY CHECK ENABLES
	OUT	PORT_B,AL
	AND	AL,RAM_PAR_ON
	OUT	PORT_B,AL
	POPF				; RESTORE FLAGS
	JNZ	SHUT4			; CONTINUE

;-----	CHECKSUM SYSTEM CODE

	PUSH	DS
	PUSH	ES			; SET SEGMENT TO TEST
	POP	DS
	SUB	BX,BX			; STARTING OFFSET
	CALL	ROM_CHECKSUM
	POP	DS			; RESTORE DATA SEGMENT
	JNZ	SHUT4			; GO IF CHECKSUM NOT OK

;-----	ENABLE NMI AND I/O-MEMORY PARITY CHECKS

	MOV	AL,CMOS_REG_D		; ENABLE NMI AND SET DEFAULT ADDRESS
	OUT	CMOS_PORT,AL

	IN	AL,PORT_B		; ENABLE PARITY
	AND	AL,RAM_PAR_ON		; ENABLE MEMORY PARITY CHECK / I/O CHECK
	OUT	PORT_B,AL

	MOV	@IO_ROM_INIT,0003H	; SET THE OFFSET
	MOV	@IO_ROM_SEG,ES		; SET THE SEGMENT

	MOV	AL,42H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  42 <><>

;-----	EXIT TO SYSTEM CODE

	CALL	DWORD PTR @IO_ROM_INIT	; GO TO SYSTEM CODE
					; VIA CALL THROUGH DATA AREA LOCATION

;-----	ENABLE NMI INTERRUPTS + ENTRY FROM SHUTDOWN WITH BOOT REQUEST

SHUT4:	MOV	AL,CMOS_REG_D		; ENABLE NMI AND SET DEFAULT ADDRESS
	OUT	CMOS_PORT,AL
	IN	AL,PORT_B		; ENABLE PARITY
	AND	AL,RAM_PAR_ON		; ENABLE MEMORY PARITY CHECK / I/O CHECK
	OUT	PORT_B,AL

	MOV	AL,43H			;	<><><><><><><><><><><><>
	OUT	MFG_PORT,AL		;	<><> CHECKPOINT  43 <><>
	STI				;  ENABLE INTERRUPTS IF DISABLED

	INT	19H			; GO TO BOOT LOADER

	HLT


PADING	PROC	NEAR			;	  INSERT PADDING
	MOV	CX,15			; GET BLANK CHARACTER COUNT
PAD1:
	MOV	AL,' '                  ; GET FILL SPACE
	CALL	PRT_HEX 		; WRITE A SPACE
	LOOP	PAD1			; LOOP TILL INSERT DONE
	MOV	AL,'-'                  ; GET DASH CHARACTER
	CALL	PRT_HEX 		; WRITE TO DISPLAY
	RET
PADING	ENDP


PRT_OK	PROC	NEAR			; PRINT "00000 KB OK"
	PUSH	AX			; SAVE WORK REGISTER
	MOV	BX,10			; SET DECIMAL CONVERT

;-----	CONVERT AND SAVE

	MOV	CX,5			; OF 5 NIBBLES XX,XXX KB
	SUB	DI,DI			; DISPLAY REGEN BUFFER POSITION
PRT_DIV:
	XOR	DX,DX
	DIV	BX			; DIVIDE BY 10
	OR	DL,30H			; MAKE INTO ASCII
	PUSH	DX			; SAVE
	LOOP	PRT_DIV

;-----	DISPLAY LAST OK MEMORY

	MOV	CX,5
PRT_DEC:
	POP	AX			; RECOVER A NUMBER
	CALL	PROT_PRT_HEX
	INC	DI			; POINT TO DISPLAY REGEN BUFFER
	LOOP	PRT_DEC
	MOV	CX,OFFSET F3B_PAD-OFFSET F3B	; LOAD MESSAGE LENGTH
	MOV	SI,OFFSET F3B		; POINT TO PRINT ' KB OK','    ' MESSAGE
PRT_LOOP:
	MOV	AL,CS:[SI]
	INC	SI
	CALL	PROT_PRT_HEX
	INC	DI			; INCREMENT BUFF PTR
	LOOP	PRT_LOOP
	POP	AX			; RECOVER WORK REGISTERS
	RET

F3B	DB	' KB OK'                ; OK MESSAGE
F3B_OK	DB	' '                     ; PAD A SPACE
F3B_PAD EQU	$
PRT_OK	ENDP

;------------------------
;	PRINTER TABLE	:
;------------------------

F4	DW	03BCH			; ADDRESS OF MONOCHROME PARALLEL ADAPTER
	DW	0378H			; BASE ADDRESS STANDARD PARALLEL ADAPTER
	DW	0278H			; ADDRESS OF ALTERNATE PARALLEL ADAPTER
F4E	LABEL	WORD

POST2	ENDP
CODE	ENDS
	END
